#include<iostream>
#include <sys/shm.h>
#include <sys/ipc.h>
#include<sys/types.h>
#include<cerrno>
#include<unistd.h>
#include<cstring>
using namespace std;
#define creater 1
#define user 2
#define SIZE 512
const string path = "/home/syx/linux/linux/shm";
const int proj_id = 0x66;
class Shm
{
public:
    Shm(const string path,int id,int w):who(w)
    {
        k = getCommKey(path, id);
        int flag;
        if (who == creater)
            flag = IPC_CREAT | IPC_EXCL|0666;
        else
            flag = IPC_CREAT;
        _shmid = shmGet(k, SIZE, flag);
        cout << k<<endl<<_shmid << endl;
        addr = (char *)Attach();
        cout << &addr << endl;
    }
    key_t getCommKey(const string &p, int id)
    {
        key_t k = ftok(p.c_str(), id);
        if(k<0)
            perror("ftok");
        return k;
    }
    int shmGet(key_t k,int size,int flag)
    {
        int shmid = shmget(k, size, flag);
        if(shmid<0)
        {
            perror("shmget");
        }
        return shmid;
    }
    ~Shm()
    {

        if(who==creater)
        {
            shmctl(_shmid, IPC_RMID, nullptr);
            
        }
        DetachShm(addr);
    }
    char* getaddr()
    {
        return addr;
    }
    void DetachShm(char* addr)
    {
        if(addr==nullptr)
            return;
        shmdt(addr);
    }
    void* Attach()
    {
        void *t=shmat(_shmid, nullptr, 0);
        if(t==nullptr)
        {
            perror("shmat");
        }
        return t;
    }
    void clear()
    {
        if(addr)
        {
            memset(addr, 0, SIZE);
        }
    }
    void Debug()
    {
        struct shmid_ds ds;
        int n = shmctl(_shmid, IPC_STAT, &ds);
        if(n<0)
            return;
        cout << ds.shm_perm.__key << endl;
        cout << ds.shm_nattch << endl;

    }

private:
    key_t k;
    int _shmid;
    int who;
    char *addr;
};
